﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Solidi
{
	/// <summary>
	/// Thread-safe
	/// </summary>
	public class PropertyDependencyComposer : IDependencyComposer
	{
		private IDependencyComposer _composer;

		public PropertyDependencyComposer(IDependencyComposer composer)
		{
			_composer = composer;
		}

		public bool TryCompose(object graphId, IDependencyContainer container, Type type, IEnumerable<IDependencyParameter> parameters, out object instance)
		{
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

			if (_composer.TryCompose(graphId, container, type, parameters, out instance))
			{
				foreach (PropertyInfo property in type.GetProperties())
				{
					Type propertyType = property.PropertyType;

					if (property.CanWrite && !propertyType.IsValueType)
					{
						MethodInfo method = property.GetSetMethod();

						if (method != null && method.GetParameters().Length == 1)
						{
							object parameterInstance;

							if (container.Resolver.TryResolve(container, new DependencyKey(property.PropertyType), out parameterInstance))
							{
								method.Invoke(instance, new object[] { parameterInstance });
							}
						}
					}
				}

				return true;
			}
			else
			{
				return false;
			}
		}

		public bool TryCompose(IDependencyContainer container, Type type, IEnumerable<IDependencyParameter> parameters, out object instance)
		{
			return _composer.TryCompose(container, type, parameters, out instance);
		}

		public bool TryDestroy(object instance)
		{
			return _composer.TryDestroy(instance);
		}
	}
}
